/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2008, 2009, 2010.

	This file is part of Maxsi Engine.

	Maxsi Engine is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Engine is distributed in the hope that it will be useful, but WITHOUT
	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
	for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Engine. If not, see <http://www.gnu.org/licenses/>.

	MaxsiEngine.dll
	A general purpose C++ library for the Maxsi Technology Project.

	MaxsiString.h
	Functions for easier string handling.

******************************************************************************/

#ifndef MaxsiString_h
#define MaxsiString_h

BeginMaxsiNamespace

//=============================================================================
//	Types of strings used within the Maxsi Engine.
//
//	MESTR* - The default internally used string type that is easy to parse.
//	char* - The System Locale that might be any encoding and thus hard to parse.
//	wchar_t* - The system wide string that is easy to parse.
//	UTF8_t* - An UTF-8 string.
//	ASCII_t* - An ASCII string.
//
//	All functions in the Maxsi Engine and sub projects should only use the
//	MESTR* string type for all internally stored and parsed strings.
//
//	If any kind of I/O is required, then strings should be converted to UTF-8 
//	on export and converted back to MESTR* on import.
//
//	char* is only used for strings in the default system locale and must not be
//	parsed. Should you need to parse a string in the system locale, you should
//	convert the string to MESTR* first.
//
//	ASCII_t* and wchar_t* can be used to store strings in and parse them,
//	though, if possible, you should try to use MESTR*.
//
//	Because UTF-8 is a multibyte encoding stored in sequences of single bytes,
//	it is quite difficult to parse UTF8_t* strings and it is recommended to
//	convert to MESTR before doing any complex parsing.
//=============================================================================

//=============================================================================
//	Declare a type for storing UTF-8 data in it.
//=============================================================================
typedef unsigned char UTF8_t;

//=============================================================================
//	Declare a type for storing UTF-16 data in it.
//=============================================================================
typedef uint16_t UTF16_t;

//=============================================================================
//	Declare a type for storing UTF-32 data in it.
//=============================================================================
typedef uint32_t UTF32_t;

//=============================================================================
//	Declare a type for storing ASCII data in it.
//=============================================================================
typedef int8_t ASCII_t;

//=============================================================================
//	Detect the properties of the wide character on this system.
//=============================================================================
#if !defined(MAXSI_WCHAR_SIZE)
	#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
		#define MAXSI_WCHAR_SIZE 4
	#else
		#define MAXSI_WCHAR_SIZE 2
	#endif
#endif

//=============================================================================
//	Define wchar_t specific macros.
//=============================================================================
#if MAXSI_WCHAR_SIZE == 4
	#define MESTRW wchar_t
	#define MESTRWL int64_t // Twice the size of wchar_t
#elif MAXSI_WCHAR_SIZE == 2
	#define MESTRW wchar_t
	#define MESTRWL int32_t // Twice the size of wchar_t
#else
	#error "Looks like you need to edit MaxsiString.h to introduce a macro for the size of wchar_t on your local system."
#endif

//=============================================================================
//	Define char specific macros.
//=============================================================================
#if __CHAR_BIT__ == 8
	#define MESTRA char
	#define MESTRAL int16_t // Twice the size of char
#else
	#error "Looks like you need to edit MaxsiString.h to introduce a macro for the size of char on your local system."
#endif

//=============================================================================
//	Define various text encodings that can be detected using a Byte Order Mark.
//=============================================================================
#define MAXSI_STR_DETECT 0
#define MAXSI_STR_SYSTEM_LOCALE 1
#define MAXSI_STR_ASCII 2
#define MAXSI_STR_UTF_8 3
#define MAXSI_STR_UTF_16_BE 4
#define MAXSI_STR_UTF_16_LE 5
#define MAXSI_STR_UTF_32_BE 6
#define MAXSI_STR_UTF_32_LE 7
//#define MAXSI_STR_LOCALTYPE // The string type used to store stuff internally.

//=============================================================================
//	Define the basic string types
//=============================================================================
#define MESTRMBS MESTRW
#define MESTRMBSL MESTRWL // Twice the size of MESTRMBS
#define MESTRNMBS MESTRA
#define MESTRNMBSL MESTRAL // Twice the size of MESTRNMBS

//=============================================================================
//	Depending on whether we use wchar_t or char as the string character, we
//	need to redirect the MESTR* functions to the corresponding string
//	function from the C runtime and our own string functions.
//=============================================================================
#ifdef Maxsi_Using_Unicode_Internally

	//=============================================================================
	//	We are using wchar_t* strings in this build.
	//=============================================================================
	#define MAXSI_STR_LOCALTYPE STR_UTF_16_LE

	//=============================================================================
	//	MESTR - The basic character of a MESTR* string
	//=============================================================================
	#define	MESTR MESTRMBS

	//=============================================================================
	//	MESTRL - A type that is twice the size of MESTR
	//=============================================================================
	#define MESTRL MESTRMBSL

	//=============================================================================
	//	MESTRLEN(string) - Returns the amount of characters in string
	//=============================================================================
	#define	MESTRLEN(string) wcslen(string)

	//=============================================================================
	//	MESTRLEN_S(string, max) - Returns the amount of characters in string, but
	//	only if a NUL termination is found before  or at max characters, otherwise
	//	SIZE_MAX is returned.
	//=============================================================================
	#define	MESTRLEN_S(string, max) wcslen_s(string, max)

	//=============================================================================
	//	MESTRCMP(string, string2) - Compares string and string2 case sensitively
	//=============================================================================
	#define	MESTRCMP(string,string2)	wcscmp(string,string2)

	//=============================================================================
	//	MESTRNCMP(string, string2, count) - Compares the first count characters
	//	in both strings case sensitively.
	//=============================================================================
	#define	MESTRNCMP(string,string2,count)	wcsncmp(string,string2,count)

	//=============================================================================
	//	MESTRNICMP(string, string2, count) - Compares the first count characters
	//	in both strings case insensitively.
	//=============================================================================
	#define	MESTRNICMP(string,string2,count)	_wcsnicmp(string,string2,count)

	//=============================================================================
	//	MESTRSIZE(string) - Returns the actual size of string in bytes without the
	//	null-termination.
	//=============================================================================	
	#define	MESTRSIZE(string)	(sizeof(MESTR)*MESTRLEN(string)) 

	//=============================================================================
	//	MESTRSIZEWN(string) - Returns the actual size of string in bytes with the
	//	null-termination.
	//=============================================================================	
	#define	MESTRSIZEWN(string)	(sizeof(MESTR)*(MESTRLEN(string)+1))
	
	//=============================================================================
	//	MESTRCPY(dest, len, src) - Copies the string from dest to src, where len is
	//	the amount of characters available at src including the null-termiantion.
	//	Fails if MESTRLENWN(src) > len. 
	//=============================================================================	
	#define MESTRCPY(dest, len, src) wcscpy_s(dest, len, src)

	//=============================================================================
	//	MESTRP(string) - Converts the MESTR to a pointer with the address of the 
	//	string. Call MESTRUP() when done with it.
	//=============================================================================
	#define MESTRP(string) (BYTE*)string

	//=============================================================================
	//	MESTRWP(string) - Converts the MESTR to a pointer to a wide char version of
	//	the string. Call MESTRUWP() when done with it.	
	//=============================================================================
	#define MESTRWP(string) (wchar_t*)string 
	
	//=============================================================================
	//	MESTRAP(string) - Converts the MESTR to a pointer to a ASCII version of the
	//	string. Call MESTRUAP() when done with it.
	//=============================================================================
	#define MESTRAP(string) WCHAR2ACSII(string)
	
	//=============================================================================
	//	MESTRCP(string) - Converts the MESTR to a pointer to a system locale
	//	version of the string. Call MESTRUCP() when done with it.
	//=============================================================================
	#define MESTRCP(string) WCHAR2CHAR(string)

	//=============================================================================
	//	MESTRUP(string) - Cleans up after a successful call to MESTRP.
	//=============================================================================
	#define MESTRUP(string)

	//=============================================================================
	//	MESTRUWP(string) - Cleans up after a successful call to MESTRWP.
	//=============================================================================
	#define MESTRUWP(string)

	//=============================================================================
	//	MESTRUAP(string) - Cleans up after a successful call to MESTRAP.
	//=============================================================================
	#define MESTRUAP(string) delete[] string

	//=============================================================================
	//	MESTRUCP(string) - Cleans up after a successful call to MESTRCP.
	//=============================================================================
	#define MESTRUCP(string) delete[] string

	//=============================================================================
	//	_MESTR(string) - Used to hardcode strings so that they will be prepended
	//	with L in wchar_t* string builds. This whole L idea is quite horrible but
	//	we shouldn't hardcode strings but rather load them from a text file
	//	instead using the Translate() function.
	//=============================================================================
	#define	_MESTR(x) L ## x // Lets not hardcode strings any longer, but instead use a string table loaded from a file to aid with localisation.
	
	//=============================================================================
	//	MESTRCAT(Dest, Size, Source) - Appends Source to the Dest string if it
	//	doesn't overflow. Size is the amount of characters available in Dest
	//	including null-termination.
	//=============================================================================
	#define MESTRCAT(Dest, Size, Source) wcscat_s(Dest, Size, Source)

	//=============================================================================
	//	MESTRITOAxx(Val, Dest, Size, Radix) - Converts the signed xx bit integer
	//	Val to a string in base Radix (10 = Decimal, 16 = Hex).
	//=============================================================================
	#define MESTRITOA(Val, Dest, Size, Radix) _itow_s(Val, Dest, Size, Radix)
	#define MESTRITOA32(Val, Dest, Size, Radix) _itow_s(Val, Dest, Size, Radix)
	#define MESTRITOA64(Val, Dest, Size, Radix) _i64tow_s(Val, Dest, Size, Radix)

	//=============================================================================
	//	MESTRUITOAxx(Val, Dest, Size, Radix) - Converts the unsigned xx bit integer
	//	Val to a string in base Radix (10 = Decimal, 16 = Hex).
	//=============================================================================
	#define MESTRUITOA(Val, Dest, Size, Radix) _ui64tow_s((uint64_t)Val, Dest, Size, Radix)
	#define MESTRUITOA32(Val, Dest, Size, Radix) _ui64tow_s((uint64_t)Val, Dest, Size, Radix)
	#define MESTRUITOA64(Val, Dest, Size, Radix) _ui64tow_s((uint64_t)Val, Dest, Size, Radix)

	//=============================================================================
	//	BuildString(Num, ...) - Combines multiple strings into a new one and
	//	returns NULL if the memory allocation failed.
	//=============================================================================
	#define BuildString BuildStringW

	//=============================================================================
	//	PrintString(Format, ...) - Creates a new string using printf formats.
	//=============================================================================
	#define PrintString PrintStringW

	//=============================================================================
	//	PrintOutput(Format, ...) - Works sort of like printf!
	//=============================================================================
	#define PrintOutput PrintOutputW

	//=============================================================================
	//	MESTR2WCHAR(String) - Converts a MESTR to a new wide character string.
	//=============================================================================
	#define MESTR2WCHAR(String) BuildString(1, String)

	//=============================================================================
	//	MESTR2CHAR(String) - Converts a MESTR to a new ascii character string.
	//=============================================================================
	#define MESTR2CHAR(String) WCHAR2CHAR(String)

	//=============================================================================
	//	MESTR2UTF8(String) - Converts a MESTR string to an UTF-8 string.
	//=============================================================================
	#define MESTR2UTF8(String) WCHAR2UTF8(String)

	//=============================================================================
	//	MESTR2ASCII(String) - Converts a MESTR string to an ASCII string.
	//=============================================================================
	#define MESTR2ASCII(String) WCHAR2ASCII(String)

	//=============================================================================
	//	CHAR2MESTR(String) - Converts a system locale string to a MESTR string.
	//=============================================================================
	#define CHAR2MESTR(String) CHAR2WCHAR(String)

	//=============================================================================
	//	WCHAR2MESTR(String) - Converts a wide character string to a MESTR string.
	//=============================================================================
	#define WCHAR2MESTR(String) BuildString(1,String)

	//=============================================================================
	//	UTF82MESTR(String) - Converts an UTF-8 string to a MESTR string.
	//=============================================================================
	#define UTF82MESTR(String) UTF82WCHAR(String)

	//=============================================================================
	//	ASCII2MESTR(String) - Converts an ASCII string to a MESTR string.
	//=============================================================================
	#define ASCII2MESTR(String) ASCII2WCHAR(String)

	//=============================================================================
	//	MCIN - The std input for the MESTR type string.
	//=============================================================================
	#define MCIN std::wcin

	//=============================================================================
	//	MCOUT - The std output for the MESTR type string.
	//=============================================================================
	#define MCOUT std::wcout

#else

	//=============================================================================
	//	We are using wchar_t* strings in this build.
	//=============================================================================
	#define MAXSI_STR_LOCALTYPE STR_SYSTEM_LOCALE

	//=============================================================================
	//	MESTR - The basic character of a MESTR* string
	//=============================================================================
	#define	MESTR MESTRNMBS

	//=============================================================================
	//	MESTRL - A type that is twice the size of MESTR
	//=============================================================================
	#define MESTRL MESTRNMBSL

	//=============================================================================
	//	MESTRLEN(string) - Returns the amount of characters in string
	//=============================================================================
	#define	MESTRLEN(string) strlen(string)

	//=============================================================================
	//	MESTRLEN_S(string, max) - Returns the amount of characters in string, but
	//	only if a NUL termination is found before  or at max characters, otherwise
	//	SIZE_MAX is returned.
	//=============================================================================
	#define	MESTRLEN_S(string, max) strlen_s(string, max)

	//=============================================================================
	//	MESTRCMP(string, string2) - Compares string and string2 case sensitively
	//=============================================================================
	#define	MESTRCMP(string,string2)	strcmp(string,string2)

	//=============================================================================
	//	MESTRNCMP(string, string2, count) - Compares the first count characters
	//	in both strings case sensitively.
	//=============================================================================
	#define	MESTRNCMP(string,string2,count)	strcmp(string,string2,count)

	//=============================================================================
	//	MESTRNICMP(string, string2, count) - Compares the first count characters
	//	in both strings case insensitively.
	//=============================================================================
	#define	MESTRNICMP(string,string2,count)	_strnicmp(string,string2,count)

	//=============================================================================
	//	MESTRSIZE(string) - Returns the actual size of string in bytes without the
	//	null-termination.
	//=============================================================================	
	#define	MESTRSIZE(string)	(sizeof(MESTR)*MESTRLEN(string)) 

	//=============================================================================
	//	MESTRSIZEWN(string) - Returns the actual size of string in bytes with the
	//	null-termination.
	//=============================================================================	
	#define	MESTRSIZEWN(string)	(sizeof(MESTR)*(MESTRLEN(string)+1))
	
	//=============================================================================
	//	MESTRCPY(dest, len, src) - Copies the string from dest to src, where len is
	//	the amount of characters available at src including the null-termiantion.
	//	Fails if MESTRLENWN(src) > len. 
	//=============================================================================	
	#define MESTRCPY(dest, len, src) strcpy_s(dest, len, src)

	//=============================================================================
	//	MESTRP(string) - Converts the MESTR to a pointer with the address of the 
	//	string. Call MESTRUP() when done with it.
	//=============================================================================
	#define MESTRP(string) (BYTE*)string

	//=============================================================================
	//	MESTRWP(string) - Converts the MESTR to a pointer to a wide char version of
	//	the string. Call MESTRUWP() when done with it.	
	//=============================================================================
	#define MESTRWP(string) CHAR2WCHAR(string)
	
	//=============================================================================
	//	MESTRAP(string) - Converts the MESTR to a pointer to a ASCII version of the
	//	string. Call MESTRUAP() when done with it.
	//=============================================================================
	#define MESTRAP(string) (char*)string 
	
	//=============================================================================
	//	MESTRCP(string) - Converts the MESTR to a pointer to a system locale
	//	version of the string. Call MESTRUCP() when done with it.
	//=============================================================================
	#define MESTRCP(string) (char*)string 

	//=============================================================================
	//	MESTRUP(string) - Cleans up after a successful call to MESTRP.
	//=============================================================================
	#define MESTRUP(string)

	//=============================================================================
	//	MESTRUWP(string) - Cleans up after a successful call to MESTRWP.
	//=============================================================================
	#define MESTRUWP(string) delete[] string

	//=============================================================================
	//	MESTRUAP(string) - Cleans up after a successful call to MESTRAP.
	//=============================================================================
	#define MESTRUAP(string)

	//=============================================================================
	//	MESTRUCP(string) - Cleans up after a successful call to MESTRCP.
	//=============================================================================
	#define MESTRUCP(string) 

	//=============================================================================
	//	_MESTR(string) - Used to hardcode strings so that they will be prepended
	//	with L in wchar_t* string builds. This whole L idea is quite horrible but
	//	we shouldn't hardcode strings but rather load them from a text file
	//	instead using the Translate() function.
	//=============================================================================
	#define	_MESTR(x) x // Lets not hardcode strings any longer, but instead use a string table loaded from a file to aid with localisation.
	
	//=============================================================================
	//	MESTRCAT(Dest, Size, Source) - Appends Source to the Dest string if it
	//	doesn't overflow. Size is the amount of characters available in Dest
	//	including null-termination.
	//=============================================================================
	#define MESTRCAT(Dest, Size, Source) strcat_s(Dest, Size, Source)

	//=============================================================================
	//	MESTRITOAxx(Val, Dest, Size, Radix) - Converts the signed xx bit integer
	//	Val to a string in base Radix (10 = Decimal, 16 = Hex).
	//=============================================================================
	#define MESTRITOA(Val, Dest, Size, Radix) _itoa_s(Val, Dest, Size, Radix)
	#define MESTRITOA32(Val, Dest, Size, Radix) _itoa_s(Val, Dest, Size, Radix)
	#define MESTRITOA64(Val, Dest, Size, Radix) _i64toa_s(Val, Dest, Size, Radix)

	//=============================================================================
	//	MESTRUITOAxx(Val, Dest, Size, Radix) - Converts the unsigned xx bit integer
	//	Val to a string in base Radix (10 = Decimal, 16 = Hex).
	//=============================================================================
	#define MESTRUITOA(Val, Dest, Size, Radix) _ui64toa_s((uint64_t)Val, Dest, Size, Radix)
	#define MESTRUITOA32(Val, Dest, Size, Radix) _ui64toa_s((uint64_t)Val, Dest, Size, Radix)
	#define MESTRUITOA64(Val, Dest, Size, Radix) _ui64toa_s((uint64_t)Val, Dest, Size, Radix)

	//=============================================================================
	//	BuildString(Num, ...) - Combines multiple strings into a new one and
	//	returns NULL if the memory allocation failed.
	//=============================================================================
	#define BuildString BuildStringA

	//=============================================================================
	//	PrintString(Format, ...) - Creates a new string using printf formats.
	//=============================================================================
	#define PrintString PrintStringA

	//=============================================================================
	//	PrintOutput(Format, ...) - Works sort of like printf!
	//=============================================================================
	#define PrintOutput PrintOutputA

	//=============================================================================
	//	MESTR2WCHAR(String) - Converts a MESTR to a new wide character string.
	//=============================================================================
	#define MESTR2WCHAR(String) WCHAR2CHAR(String)

	//=============================================================================
	//	MESTR2CHAR(String) - Converts a MESTR to a new ascii character string.
	//=============================================================================
	#define MESTR2CHAR(String) BuildString(1, String)

	//=============================================================================
	//	MESTR2UTF8(String) - Converts a MESTR string to an UTF-8 string.
	//=============================================================================
	#define MESTR2UTF8(String) CHAR2UTF8(String)

	//=============================================================================
	//	MESTR2ASCII(String) - Converts a MESTR string to an ASCII string.
	//=============================================================================
	#define MESTR2ASCII(String) CHAR2ASCII(String)

	//=============================================================================
	//	CHAR2MESTR(String) - Converts a system locale string to a MESTR string.
	//=============================================================================
	#define CHAR2MESTR(String) BuildString(1, String)

	//=============================================================================
	//	WCHAR2MESTR(String) - Converts a wide character string to a MESTR string.
	//=============================================================================
	#define WCHAR2MESTR(String) WCHAR2CHAR(String)

	//=============================================================================
	//	UTF82MESTR(String) - Converts an UTF-8 string to a MESTR string.
	//=============================================================================
	#define UTF82MESTR(String) UTF82CHAR(String)

	//=============================================================================
	//	ASCII2MESTR(String) - Converts an ASCII string to a MESTR string.
	//=============================================================================
	#define ASCII2MESTR(String) ASCII2CHAR(String)

	//=============================================================================
	//	MCIN - The std input for the MESTR type string.
	//=============================================================================
	#define MCIN std::cin

	//=============================================================================
	//	MCOUT - The std output for the MESTR type string.
	//=============================================================================
	#define MCOUT std::cout

	//=============================================================================
	//	MESTRPRINTF - Prints MESTR characters to the console output.
	//=============================================================================
	#define MESTRPRINTF printf

#endif

//=============================================================================
//	MESTR* BuildString(size_t NumParameters, ...);
//
//	Combines NumParameter strings into one new string. Returns the new string
//	on success or NULL if the memory allocation failed.
//=============================================================================
LINKCPP	char*		BuildStringA(size_t NumParameters, ...);
LINKCPP	wchar_t*	BuildStringW(size_t NumParameters, ...);

//=============================================================================
//	int MESTRCMP(const MESTR* String1, const MESTR* String2)
//
//	This function starts comparing the first character of each string. If they
//	are equal to each other, it continues with the following pairs until the
//	characters differ or until a terminanting null-character is reached.
//	Returns an integral value indicating the relationship between the strings:
//	A zero value indicates that both strings are equal. A value greater than
//	zero indicates that the first character that does not match has a greater
//	value in str1 than in str2, a value less than zero indicates the opposite.
//=============================================================================
LINKCPP	int MESTRCMP(const char* str1, const char* str2);
LINKCPP	int MESTRCMP(const wchar_t* str1, const char* str2);
LINKCPP	int MESTRCMP(const char* str1, const wchar_t* str2);
LINKCPP	int MESTRCMP(const wchar_t* str1, const wchar_t* str2);

//=============================================================================
//	int MESTRICMP(const MESTR* String1, const MESTR* String2)
//
//	Like MESTRCMP(str1, str2), but case insensitive.
//=============================================================================
LINKCPP	int MESTRICMP(const char* str1, const char* str2);
LINKCPP	int MESTRICMP(const wchar_t* str1, const char* str2);
LINKCPP	int MESTRICMP(const char* str1, const wchar_t* str2);
LINKCPP	int MESTRICMP(const wchar_t* str1, const wchar_t* str2);

//=============================================================================
//	size_t FindString[Ex](MESTR* String1 [, size_t String1Len], MESTR* String2
//	[, size_t String2Len]);
//
//	Searches inside String1 [of the length String1Len] for the first occurence
//	of String2 [of length String2Len] and returns the offset where String2 was
//	found or SIZE_MAX if String2 wasn't found inside String1. 
//=============================================================================
LINK size_t FindString(MESTR* String1, MESTR* String2);
LINK size_t FindStringEx(MESTR* String1, size_t String1Len, MESTR* String2, size_t String2Len);

//=============================================================================
//	MESTR* StringReplace(MESTR* Search, MESTR* Insert, MESTR* Haystack);
//
//	Returns a string where the every occurence of Search in Heystack has been
//	replaced by Insert. Might have to do memory allocations. Do not use Search
//	after calling this function as it might be delete[]'d. Instead you should
//	use the return value. Returns NULL upon failure.
//=============================================================================
LINK MESTR* StringReplace(MESTR* Search, MESTR* Insert, MESTR* Haystack);

//=============================================================================
//	MESTR* SubString(size_t Start, size_t Length, MESTR* ExtractFrom);
//
//	Extracts Length characters of the string ExtractFrom starting at Start and
//	returns it as a new string. Returns NULL upon failure.
//=============================================================================
LINK MESTR* SubString(size_t Start, size_t Length, MESTR* ExtractFrom);

//=============================================================================
//	size_t SkipWhiteSpace(MESTR* Buffer, [size_t BufferLen]);
//
//	Skips anywhite space in Buffer and returns the offset of the next
//	non-whitespace character. Returns SIZE_MAX is the rest of the string is
//	whitespace [or BufferLen is exceeded].
//=============================================================================
LINKCPP	size_t MAXSI_FORCE_INLINE SkipWhiteSpace(MESTR* Buffer);
LINKCPP	size_t MAXSI_FORCE_INLINE SkipWhiteSpace(MESTR* Buffer, size_t BufferLen);

//=============================================================================
//	size_t NextWhiteSpace(MESTR* Buffer, [size_t BufferLen]);
//
//	Returns the location of the next whitespace. Returns SIZE_MAX if none is
//	found [or BufferLen is exceeded].
//=============================================================================
LINKCPP size_t MAXSI_FORCE_INLINE NextWhiteSpace(MESTR* Buffer);
LINKCPP size_t MAXSI_FORCE_INLINE NextWhiteSpace(MESTR* Buffer, size_t BufferLen);
LINKCPP size_t MAXSI_FORCE_INLINE NextNonQuotedWhiteSpace(MESTR* Buffer);
LINKCPP size_t MAXSI_FORCE_INLINE NextNonQuotedWhiteSpace(MESTR* Buffer, size_t BufferLen);

//=============================================================================
//	size_t NextLine(MESTR* Buffer, [size_t BufferLen]);
//
//	Returns the location of the beginning of the next line. Returns SIZE_MAX if
//	none is found [or BufferLen is exceeded].
//=============================================================================
LINKCPP size_t MAXSI_FORCE_INLINE NextLine(MESTR* Buffer);
LINKCPP size_t MAXSI_FORCE_INLINE NextLine(MESTR* Buffer, size_t BufferLen);

//=============================================================================
//	size_t strlen_s(char* String, size_t MaxLen);
//
//	Returns the length of String or SIZE_MAX if no null termination is found
//	before the function reaches String[MaxLen].
//=============================================================================
LINK size_t strlen_s(char* String, size_t MaxLen);

//=============================================================================
//	size_t wcslen_s(char* String, size_t MaxLen);
//
//	Returns the length of String or SIZE_MAX if no null termination is found
//	before the function reaches String[MaxLen].
//=============================================================================
LINK size_t wcslen_s(wchar_t* String, size_t MaxLen);

//=============================================================================
//	StringType_t GuessStringEncoding(BYTE* String, size_t StringSize);
//
//	Looks for any Byte Order Marks near the start of the string and guesses
//	whether it is ASCII (default), UTF-8, UTF-16 (Big Endian or Little Endian).
//	Returns a STR_* value depending on what is found. If no BOM is found, then
//	the function defaults to ASCII and you should parse the string as such.
//	StringSize is the size of the string in bytes, including any
//	null-termination.
//=============================================================================
LINK StringType_t GuessStringEncoding(BYTE* String, size_t StringSize);


// TODO: Document the rest of these functions!
LINK char*		WCHAR2CHAR(const wchar_t* Input); // Converts wide string to the system locale.
LINK UTF8_t*	WCHAR2UTF8(const wchar_t* Input); // Converts wide string to UTF-8.
LINK ASCII_t*	WCHAR2ASCII(const wchar_t* Input); // Converts wide string to ASCII.

LINK wchar_t*	CHAR2WCHAR(const char* Input); // Converts system locale to wide string.
LINK UTF8_t*	CHAR2UTF8(const char* Input); // Converts system locale to UTF-8.
LINK ASCII_t*	CHAR2ASCII(const char* input); // Converts system locale to ASCII.

LINK char*		UTF82CHAR(const UTF8_t* Input); // Converts UTF-8 to the system locale.
LINK wchar_t*	UTF82WCHAR(const UTF8_t* Input); // Converts UTF-8 to wide string.
LINK ASCII_t*	UTF2ASCII(const UTF8_t* Input); // Converts UTF-8 to ASCII.

LINK char*		ASCII2CHAR(const ASCII_t* Input); // Converts ASCII to the system locale.
LINK UTF8_t*	ASCII2UTF8(const ASCII_t* Input); // Converts ASCII to UTF-8.
LINK wchar_t*	ASCII2WCHAR(const ASCII_t* Input); // Converts ASCII to wide string.

LINK BYTE* RecodeString(const char* From, BYTE* Input, size_t InputSize, const char* To, size_t ToCharSize);
LINK UTF8_t* RecodeStringAsUTF8(const char* From, BYTE* Input, size_t InputSize);
LINK MESTR* RecodeStringAsMESTR(const char* From, BYTE* Input, size_t InputSize);

LINKCPP	MESTR*		EvaluateQuote	(MESTR* Buffer);
LINKCPP	MESTR*		EvaluateQuote	(MESTR* Buffer, size_t Outlen);
LINK	size_t		FindChar		(MESTR* Buffer, MESTR CharToFind, size_t BufferLen);
LINK	size_t		FindCharPrev	(MESTR* Buffer, MESTR CharToFind, size_t Begin);
LINK	bool		str_replace		(MESTR* input, MESTR* find, MESTR* replace);
LINK	bool		buf_replace		(MESTR* input,size_t input_Len, MESTR* find, size_t find_Len, MESTR* replace, size_t replace_Len);

LINK	char		FromHEXA		(char Hex);
LINK	wchar_t		FromHEXW		(wchar_t Hex);
LINK	MESTR		FromHEXM		(MESTR Hex);
LINK	short		ToHEXA			(char In);
LINK	int			ToHEXW			(wchar_t In);
LINK	MESTRL		ToHEXM			(MESTR In);	
LINK	bool		DecodeURL		(char* URL);
LINK	char*		EncodeURL		(char* URL);	
LINK	MESTR*		EncodeFileName	(MESTR* FileName);
LINK	bool		ShouldCharBeEncodedURL		(MESTR In);
LINK	bool		ShouldCharBeEncodedFileName	(MESTR In);
LINK	size_t		HEXTOI			(MESTR* Text);

LINK	char*		PrintStringFormatToChar(char* Format);
LINK	wchar_t*	PrintStringFormatToWChar(wchar_t* Format);
LINK	size_t		PrintStringVALength(char* Format, va_list ap);
LINK	size_t		PrintStringVWLength(char* Format, va_list ap);
LINK	char*		PrintStringVA(size_t ResultLength, char* Format, va_list ap);
LINK	wchar_t*	PrintStringVW(size_t ResultLength, wchar_t* Format, va_list ap);
LINK	char*		PrintStringA(char* Format, ...);
LINK	wchar_t*	PrintStringW(char* Format, ...);
LINK	size_t		PrintOutputA(char* Format, ...);
LINK	size_t		PrintOutputW(char* Format, ...);

//=============================================================================
//	String table of all the error codes. (Defined in MaxsiError.cpp)
//=============================================================================
MESTR* MaxsiErrorName(MaxsiError Error);

EndMaxsiNamespace

#endif
